package com.jrsoft.bim.util;

import com.jrsoft.bim.dto.PointDTO;
import com.jrsoft.bim.dto.excel.FieldDTO;
import com.jrsoft.bim.util.math.Line;
import com.jrsoft.bim.util.math.LinearEquation;
import com.jrsoft.bim.util.math.Point;
import com.sun.org.apache.xpath.internal.operations.And;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
import org.apache.xmlbeans.impl.xb.xsdschema.Public;
import org.nfunk.jep.JEP;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;

/**
 * ${DESCRIPTION}
 *
 * @author Blueeyedboy
 * @create 2019-12-30 9:40 PM
 **/
public class MathUtil {
	public static final double ZERO = 0.0;
	public static final String ZERO_STR = "0.0000000000000001";

	// 'double类型的计算精度
	public static String C_Str_Accuracy = "0.00000";
	public static double C_D_Accuracy = 0.000001;
	public static double c_WallThick = 5;
	public static double C_D_Pi = 3.14159265358979;

	/**
	 * 判断点是否在多边形内(基本思路是用交点法)
	 *
	 * @param point
	 * @param boundaryPoints
	 * @return
	 */
	public static boolean isPointInPolygon(PointDTO point, PointDTO[] boundaryPoints) {
		// 防止第一个点与最后一个点相同
		if (boundaryPoints != null && boundaryPoints.length > 0
				&& boundaryPoints[boundaryPoints.length - 1].equals(boundaryPoints[0])) {
			boundaryPoints = Arrays.copyOf(boundaryPoints, boundaryPoints.length - 1);
		}
		int pointCount = boundaryPoints.length;

		// 首先判断点是否在多边形的外包矩形内，如果在，则进一步判断，否则返回false
		if (!isPointInRectangle(point, boundaryPoints)) {
			return false;
		}

		// 如果点与多边形的其中一个顶点重合，那么直接返回true
		for (int i = 0; i < pointCount; i++) {
			if (point.equals(boundaryPoints[i])) {
				return true;
			}
		}

		/**
		 * 基本思想是利用X轴射线法，计算射线与多边形各边的交点，如果是偶数，则点在多边形外，否则在多边形内。还会考虑一些特殊情况，如点在多边形顶点上
		 * ， 点在多边形边上等特殊情况。
		 */
		// X轴射线与多边形的交点数
		int intersectPointCount = 0;
		// X轴射线与多边形的交点权值
		float intersectPointWeights = 0;
		// 浮点类型计算时候与0比较时候的容差
		double precision = 2e-10;
		// 边P1P2的两个端点
		PointDTO point1 = boundaryPoints[0], point2;
		// 循环判断所有的边
		for (int i = 1; i <= pointCount; i++) {
			point2 = boundaryPoints[i % pointCount];

			/**
			 * 如果点的y坐标在边P1P2的y坐标开区间范围之外，那么不相交。
			 */
			if (point.getY() < Math.min(point1.getY(), point2.getY())
					|| point.getY() > Math.max(point1.getY(), point2.getY())) {
				point1 = point2;
				continue;
			}

			/**
			 * 此处判断射线与边相交
			 */
			if (point.getY() > Math.min(point1.getY(), point2.getY())
					&& point.getY() < Math.max(point1.getY(), point2.getY())) {// 如果点的y坐标在边P1P2的y坐标开区间内
				if (point1.getX() == point2.getX()) {// 若边P1P2是垂直的
					if (point.getX() == point1.getX()) {
						// 若点在垂直的边P1P2上，则点在多边形内
						return true;
					} else if (point.getX() < point1.getX()) {
						// 若点在在垂直的边P1P2左边，则点与该边必然有交点
						++intersectPointCount;
					}
				} else {// 若边P1P2是斜线
					if (point.getX() <= Math.min(point1.getX(), point2.getX())) {// 点point的x坐标在点P1和P2的左侧
						++intersectPointCount;
					} else if (point.getX() > Math.min(point1.getX(), point2.getX())
							&& point.getX() < Math.max(point1.getX(), point2.getX())) {// 点point的x坐标在点P1和P2的x坐标中间
						double slopeDiff = 0.0d;
						if (point1.getY() > point2.getY()) {
							slopeDiff = (point.getY() - point2.getY()) / (point.getX() - point2.getX())
									- (point1.getY() - point2.getY()) / (point1.getX() - point2.getX());
						} else {
							slopeDiff = (point.getY() - point1.getY()) / (point.getX() - point1.getX())
									- (point2.getY() - point1.getY()) / (point2.getX() - point1.getX());
						}
						if (slopeDiff > 0) {
							if (slopeDiff < precision) {// 由于double精度在计算时会有损失，故匹配一定的容差。经试验，坐标经度可以达到0.0001
								// 点在斜线P1P2上
								return true;
							} else {
								// 点与斜线P1P2有交点
								intersectPointCount++;
							}
						}
					}
				}
			} else {
				// 边P1P2水平
				if (point1.getY() == point2.getY()) {
					if (point.getX() <= Math.max(point1.getX(), point2.getX())
							&& point.getX() >= Math.min(point1.getX(), point2.getX())) {
						// 若点在水平的边P1P2上，则点在多边形内
						return true;
					}
				}
				/**
				 * 判断点通过多边形顶点
				 */
				if (((point.getY() == point1.getY() && point.getX() < point1.getX()))
						|| (point.getY() == point2.getY() && point.getX() < point2.getX())) {
					if (point2.getY() < point1.getY()) {
						intersectPointWeights += -0.5;
					} else if (point2.getY() > point1.getY()) {
						intersectPointWeights += 0.5;
					}
				}
			}
			point1 = point2;
		}

		if ((intersectPointCount + Math.abs(intersectPointWeights)) % 2 == 0) {// 偶数在多边形外
			return false;
		} else { // 奇数在多边形内
			return true;
		}
	}

	/**
	 * 判断点是否在矩形内在矩形边界上，也算在矩形内(根据这些点，构造一个外包矩形)
	 *
	 * @param point
	 *            点对象
	 * @param boundaryPoints
	 *            矩形边界点
	 * @return
	 */
	public static boolean isPointInRectangle(PointDTO point, PointDTO[] boundaryPoints) {
		PointDTO southWestPoint = getSouthWestPoint(boundaryPoints); // 西南角点
		PointDTO northEastPoint = getNorthEastPoint(boundaryPoints); // 东北角点
		return (point.getX() >= southWestPoint.getX() && point.getX() <= northEastPoint.getX()
				&& point.getY() >= southWestPoint.getY() && point.getY() <= northEastPoint.getY());

	}

	/**
	 * 根据这组坐标，画一个矩形，然后得到这个矩形西南角的顶点坐标
	 *
	 * @param vertexs
	 * @return
	 */
	private static PointDTO getSouthWestPoint(PointDTO[] vertexs) {
		double minLng = vertexs[0].getX(), minLat = vertexs[0].getY();
		for (PointDTO PointDTO : vertexs) {
			double lng = PointDTO.getX();
			double lat = PointDTO.getY();
			if (lng < minLng) {
				minLng = lng;
			}
			if (lat < minLat) {
				minLat = lat;
			}
		}
		return new PointDTO(minLng, minLat);
	}

	/**
	 * 根据这组坐标，画一个矩形，然后得到这个矩形东北角的顶点坐标
	 *
	 * @param vertexs
	 * @return
	 */
	private static PointDTO getNorthEastPoint(PointDTO[] vertexs) {
		double maxLng = 0.0d, maxLat = 0.0d;
		for (PointDTO PointDTO : vertexs) {
			double lng = PointDTO.getX();
			double lat = PointDTO.getY();
			if (lng > maxLng) {
				maxLng = lng;
			}
			if (lat > maxLat) {
				maxLat = lat;
			}
		}
		return new PointDTO(maxLng, maxLat);
	}

	/**
	* 获取两线段交点
	* @param 
	* @return 
	* @author Blueeyedboy
	* @create 12/31/2019 12:24 PM
	**/
	public  static Point getLineSegmentCrossPoint(double x1, double y1, double x2, double y2, double x3,double y3,double x4,double y4){
		return getLineSegmentCrossPoint(new Point(x1,y1),new Point(x2,y2),new Point(x3,y3),new Point(x4,y4));
	}

	public  static Point getLineSegmentCrossPoint(Point a1, Point a2,Point b1, Point b2){
			LinearEquation ans = new LinearEquation(a1, a2, b1, b2);
			if (ans.solve()) {
				Point p = new Point(ans.getX(),ans.getY() == 0?0:ans.getY());
				return p;
			} else{
				System.out.println("The two lines do not cross");
			}
			return null;

	}

	/**
	* 判断是否平行线
	* @param
	* @return 
	* @author Blueeyedboy
	* @create 1/1/2020 1:42 PM
	**/
	public static boolean isParallelLines(Double lineSlope1,Double lineSlope2){
		// 斜率为null表示垂直x轴
		if(lineSlope1 == null){
			if(lineSlope2 == null){
				// 两条线都是垂直
				return true;
			}else{
				return false;
			}
		}else{
			if(lineSlope2 == null){
				//
				return false;
			}else{
				if(compareDouble(lineSlope1,lineSlope2) ==0){
					return true;
				}else{
					return false;
				}
			}
		}
	}

	/**
	* 计算直线的斜率
	* @param
	* @return 
	* @author Blueeyedboy
	* @create 1/1/2020 11:07 AM
	**/
	public static Double getLineSlope(Point p1,Point p2){
		double x1 = p1.x;
		double y1 = p2.y;
		double x2 = p2.x;
		double y2 = p2.y;
		// 如果两个点x相同，说明两个点连成的线是垂直x轴
		if(compareDouble(x1,x2) ==0){
			return null;
		}
		return (y1-y2)/(x1-x2);
	}

	/**
	* 判断点到线的距离
	* @param 
	* @return 
	* @author Blueeyedboy
	* @create 1/1/2020 1:50 PM
	**/
	public static double getLineDistince(Line line,Point p){
		double x1 = line.getStart().getX();
		double y1 = line.getStart().getY();
		double x2 = line.getEnd().getX();
		double y2 = line.getEnd().getY();
		double x0 = p.getX();
		double y0 = p.getY();
		// 判断线是否垂线
		if(compareDouble(x1,x2) == 0){
			return Math.abs(x0-x1);
		}
		double a = line.getA();
		double b = line.getB();
		double c = line.getC();

		double d = Math.abs(a*x0+b*y0+c)/Math.sqrt(a*a+b*b);
		// 计算垂足
		/*double px=(b*b*x0-a*b*y0-a*c)/(a*a+b*b);
		double py=(a*a*y0-a*b*x0-b*c)/(a*a+b*b);*/
		return d;
	}

	/**
	* 计算亮点的直线方程的参数a,b,c
	* @param 
	* @return 
	* @author Blueeyedboy
	* @create 12/31/2019 2:59 PM
	**/
	public static Line getLine(Point p1, Point p2){
		Line line = new Line();
		line.a = p2.y - p1.y;
		line.b = p1.x - p2.x;
		line.c = p2.x * p1.y - p1.x * p2.y;
		line.setStart(p1);
		line.setEnd(p2);
		return line;
	}

	public static double formatNum(double d){
		DecimalFormat df = new DecimalFormat("#.00000");
		return Double.parseDouble(df.format(d));
	}

	/**
	* 比较两个数的大小
	* @param 
	* @return 
	* @author Blueeyedboy
	* @create 12/31/2019 6:23 PM
	**/
	public static int compareDouble(double d1,double d2){
		d1 = formatNum(d1);
		d2 = formatNum(d2);
		if( (d1 - d2) > 0 ){
			return 1;
		}else if((d1 - d2) < 0){
			return -1;
		}else{
			return 0;
		}
	}

	/**
	 * 判断一个点在一条线上
	 * @param
	 * @return
	 * @author Blueeyedboy
	 * @create 12/31/2019 3:56 PM
	 **/
	public static boolean isInLine(Line line, Point p){
		boolean isInLine = false;
		double sum = line.a * p.x + line.b * p.y + line.c;
		if( sum <= C_D_Accuracy && sum>0){
			isInLine = true;
		}else{
			isInLine = false;
		}
		return isInLine;
	}

	/**
	* 判断一个点在一条线上
	* @param
	* @return
	* @author Blueeyedboy
	* @create 12/31/2019 3:56 PM
	**/
	public static boolean isInLineSegment(Line line, Point p){
		boolean isInLine = false;
		double sum = line.a * p.x + line.b * p.y + line.c;
//		System.out.println(line+"====="+sum+"------"+p);
		if( sum <= C_D_Accuracy && sum>=0){
			Point startPt = line.start;
			Point endPt = line.end;
//			System.out.println("-------1------"+(p.x <= endPt.x && p.x >= startPt.x && p.y <= endPt.y && p.y >= startPt.y));
//			System.out.println("-------2------"+(compareDouble(p.x, endPt.x) == 0 && compareDouble(p.y, endPt.y) == 0));
//			System.out.println("-------3------"+(compareDouble(p.x, startPt.x) == 0 && compareDouble(p.y, startPt.y) == 0) );
			if ((p.x <= endPt.x && p.x >= startPt.x && p.y <= endPt.y && p.y >= startPt.y)
					|| (compareDouble(p.x, endPt.x) == 0
					&& compareDouble(p.y, endPt.y) == 0)
					|| (compareDouble(p.x, startPt.x) == 0
					&& compareDouble(p.y, startPt.y) == 0) ){
				isInLine = true;
			}

		}else{
			isInLine = false;
		}
		return isInLine;
	}

	/**
	* 计算两点距离
	* @param 
	* @return 
	* @author Blueeyedboy
	* @create 12/31/2019 4:03 PM
	**/
	public static double getDistance(Point p1,Point p2){
		return Math.sqrt(Math.abs((p1.getX() - p2.getX())* (p1.getX() - p2.getX())+(p1.getY() - p2.getY())* (p1.getY() - p2.getY())));
	}

	/**
	* 计算两条直线交点
	* @param 
	* @return 
	* @author Blueeyedboy
	* @create 12/31/2019 4:04 PM
	**/
	public static Point getLineCrossPoint(Point p1, Point p2,Point p3, Point p4){
		Point pt = new Point();

		Line line1 = getLine(p1,p2);
		Line line2 = getLine(p3,p4);
		double m = line1.a * line2.b - line2.a * line1.b;
		// '如果斜率相同, 说明是平行线
		if (0 <= Math.abs(m) &&  Math.abs(m) <= C_D_Accuracy){
			// 表示两条线重合
			if(isInLine(line2,p2)){

			}
			return null;
		}
		pt.x = (line2.c * line1.b - line1.c * line2.b) / m;
		pt.y = (line1.c * line2.a - line2.c * line1.a) / m;
		if(pt.x - 0 == 0){
			pt.x = 0;
		}
		if(pt.y - 0 == 0){
			pt.y = 0;
		}
		return pt;
			//****************************************************************************************
			//  求二条直线的交点的公式
			//  有如下方程 (x-x1)/(y-y1) = (x2-x1)/(y2-y1) ==> a1*x+b1*y=c1
			//            (x-x3)/(y-y3) = (x4-x3)/(y4-y3) ==> a2*x+b2*y=c2
			//  则交点为
			//                x= | c1 b1|  / | a1 b1 |      y= | a1 c1| / | a1 b1 |
			//                   | c2 b2|  / | a2 b2 |         | a2 c2| / | a2 b2 |
			//
			//   a1= y2-y1
			//   b1= x1-x2
			//   c1= x1*y2-x2*y1
			//   a2= y4-y3
			//   b2= x3-x4
			//   c2= x3*y4-x4*y3

			/*double a1 = p2.y - p1.y;
		double b1 = p1.x - p2.x;
		double c1 = p1.x*p2.y - p2.x*p1.y;
		double a2 = p4.y - p3.y;
		double b2 = p3.x - p4.x;
		double c2 = p3.x*p4.y - p4.x*p3.y;
		double det= a1*b2 - a2*b1;

			if(det == 0) {
				return null;
			}

			crossPoint.x = (c1*b2 - c2*b1)/det;
			crossPoint.y = (a1*c2 - a2*c1)/det;

			// Now this is cross point of lines
			// Do we need the cross Point of segments(need to judge x,y within 4 endpoints)
			// 是否要判断线段相交
			if((Math.abs(crossPoint.x -(p1.x+p2.x)/2) <= Math.abs(p2.x-p1.x)/2) &&
					(Math.abs(crossPoint.y -(p1.y+p2.y)/2) <= Math.abs(p2.y-p1.y)/2) &&
					(Math.abs(crossPoint.x -(p3.x+p4.x)/2) <= Math.abs(p4.x-p3.x)/2) &&
					(Math.abs(crossPoint.y -(p3.y+p4.y)/2) <= Math.abs(p4.y-p3.y)/2))
			{
				return crossPoint;
			}
*/
	}

	/**
	 * java将字符串转换成可执行代码 工具类
	 * @param map
	 * @return
	 */
	public static Object evaluate2(String expression, Map<String, Object> map) {
		JexlEngine jexl = new JexlEngine();
		Expression exp = jexl.createExpression(expression);
		JexlContext jc = new MapContext();
		for (String key : map.keySet()) {
			jc.set(key, map.get(key));
		}
		if (null == exp.evaluate(jc)) {
			return "";
		}
		return exp.evaluate(jc);
	}

	/**
	 * java将字符串转换成可执行代码 工具类
	 * @param map
	 * @return
	 */
	public static Object evaluate(String expression, Map<String, Object> map) {
		JEP jep = new JEP();
		// 给变量赋值
		for (String key : map.keySet()) {
			expression = expression.replace(key,map.get(key).toString());
		}
		// 运算
		jep.parseExpression(expression);
		if(StringUtil.isNotBlank(jep.getErrorInfo())){
			throw new RuntimeException(jep.getErrorInfo());

		}
		if("NaN".equals(String.valueOf(jep.getValue()))){
			return ZERO;
		}
		return jep.getValue();
	}

	/**
	 * java将字符串转换成可执行代码 工具类
	 * @param map
	 * @return
	 */
	public static double evaluateDouble(String expression, Map<String, Object> map) {
		JEP jep = new JEP();
		// 给变量赋值
		for (String key : map.keySet()) {
			expression = expression.replace(key,map.get(key).toString());
		}
		// 运算
		jep.parseExpression(expression);
		if(StringUtil.isNotBlank(jep.getErrorInfo())){
			throw new RuntimeException(jep.getErrorInfo());

		}
		return ConvertV2Util.getDoubleValue(jep.getValue());
	}

	/**
	 * 计算(V)梁中求和公式
	 * @param
	 * @return
	 * @author Blueeyedboy
	 * @create 4/30/2020 5:59 PM
	 **/
	public static double getVSum(Map<String,FieldDTO> fields,int end){
		double sum = 0;
		for(int i = 1;i<=end;i++){
			double kl28 = getDoubleValue(fields.get("KL(28,"+i+")"));
			double kl29 = getDoubleValue(fields.get("KL(29,"+i+")"));
			double zz3 = getDoubleValue(fields.get("ZZ(3,"+i+")"));
			sum += kl28*kl29*zz3;
		}
		return sum;
	}

	public static String getNumStringSum(Map<String,FieldDTO> fields,String prefix,int start,int begin,int end){
		double sum = 0;
		for(int i = begin;i<=end;i++){
			String key = prefix+"("+start+","+i+")";
			double v = getDoubleValue(fields.get(key));
			sum += v;
		}
		return String.valueOf(sum);
	}

	public static String getNumStringPowSum(Map<String,FieldDTO> fields,String prefix,int start,int begin,int end){
		double sum = 0;
		for(int i = begin;i<=end;i++){
			String key = prefix+"("+start+","+i+")";
			double v = getDoubleValue(fields.get(key));
			sum += Math.pow(v,2);
		}
		return String.valueOf(sum);
	}

	public static double
	getNumSum(Map<String,FieldDTO> fields,String prefix,int start,int begin,int end){
		double sum = 0;
		for(int i = begin;i<=end;i++){
			String key = prefix+"("+start+","+i+")";
			double v = getDoubleValue(fields.get(key));
			sum += v;
		}
		return sum;
	}

	public static String getNumStringNotZero(Map<String,FieldDTO> fields,String prefix,int start,int end){
		String key = prefix+"("+start+","+end+")";
		double v = getDoubleValue(fields.get(key));
		if(v == 0){
			return ZERO_STR;
		}else{
			return String.valueOf(v);
		}

	}

	public static String getNumStringNotZero(FieldDTO field){
		double v = getDoubleValue(field);
		if(v == 0){
			return ZERO_STR;
		}else{
			return String.valueOf(v);
		}
	}

	public static String getNumString(Map<String,FieldDTO> fields,String prefix,int start,int end){
		String key = prefix+"("+start+","+end+")";
		double v = getDoubleValue(fields.get(key));
		return String.valueOf(v);
	}

	public static double getDoubleValue(FieldDTO field){
		if(field != null){
			if(StringUtil.isNotBlank(field.getValue())){
				String v = field.getValue();
				if(v.endsWith("*")){
					v = v.substring(0,v.length()-1);
				}
				double r =  Double.parseDouble(v);
				if(r == 0){
					return ZERO;
				}
				return r;
			}
		}

		return ZERO;
	}

	public static double getDoubleValue(Object o){
		if(o != null){
			try{
				if(o.toString().indexOf("Infinity")>-1){
					return 0;
				}else if(o.toString().indexOf("NaN")>-1){
					return 0;
				}
				NumberFormat nf = NumberFormat.getInstance();
				nf.setGroupingUsed(false);
				String r = nf.format(Double.parseDouble(o.toString()));
				double re =  Double.parseDouble(r.toLowerCase());
				if(re == 0){
					return ZERO;
				}
				return re;
			}catch (Exception e){

				return 0;
			}
		}

		return 0;
	}

	public static int getIntegerValue(FieldDTO field){
		if(field != null){
			if(StringUtil.isNotBlank(field.getValue())){
				String v = field.getValue();
				if(v.indexOf(".")>-1){
					return Integer.parseInt(v.substring(0,v.indexOf(".")));
				}else{
					return Integer.parseInt(v);
				}
			}
		}

		return 0;
	}

	public static String getNumStringValue(FieldDTO field){
		if(field != null){
			if(StringUtil.isNotBlank(field.getValue())){
				double re =  Double.parseDouble(field.getValue().toLowerCase());
				if(re == 0){
					return String.valueOf(ZERO);
				}
				return String.valueOf(re);

			}
		}

		return "0";
	}

	public static double getMax(double... num){
		return Arrays.stream(num).max().getAsDouble();
	}

	public static void main(String[] args) {
		PointDTO p1 = new PointDTO(0d,0d);
		PointDTO p2 = new PointDTO(0d,10d);
		PointDTO p3 = new PointDTO(10d,10d);
		PointDTO p4 = new PointDTO(10d,0d);

		PointDTO p = new PointDTO(0d,0d);
		System.out.println(p+"---"+isPointInRectangle(p,new PointDTO[]{p1,p2,p3,p4}));
		p = new PointDTO(1d,1d);
		System.out.println(p+"---"+isPointInRectangle(p,new PointDTO[]{p1,p2,p3,p4}));

		System.out.println("------交点------"+getLineSegmentCrossPoint(new Point(0,0),new Point(0,10d),new Point(0,0),new Point(10d,10d)));
		System.out.println("------交点------"+getLineCrossPoint(new Point(0,0),new Point(0,10d),new Point(1,10),new Point(10d,10d)));
		System.out.println("------交点------"+getLineCrossPoint(new Point(0,2),new Point(2,0d),new Point(1.5,1.5),new Point(2,2)));
		System.out.println("------交点------"+getLineSegmentCrossPoint(0,0,0,10,0,10,10,10));
		System.out.println("------交点------"+getLineSegmentCrossPoint(0,0,0,10,1,10,10,10));

		System.out.println("------距离------"+getDistance(new Point(0,2),new Point(2,2d)));
		System.out.println("------距离------"+getDistance(new Point(4370,400),new Point(4370,0)));
		System.out.println("------距离------"+getDistance(new Point(4370,0),new Point(4370,400)));


//		double t = (0*(3.14/4)*0*(700.0+(0+12)*18.0+0*0+4000.0/3)+*(3.14/4)*0.0*(0*0.0+0.0/3+700.0+(0+12)*18.0) *7.85;


		double t = ((18.0*(3.14/4)*2.0*(0.75*700.0+(0+10)*0+18.0*(3.14/4)*2.0*(0*0+4000.0/4))+((6900.0/4+11200.0/4+600.0)*0.0*(3.14/4)*0.0)+0.0)*(3.14/4)*0.0*((0*0.0+0.0/4)+(0.75*700.0+(0+10)*0.0))*2.0*(3.14/4)*18.0)*7.85;
		t = ((6720.0/800.0*2+(15200.0-2*6720.0)/0.0)*3.14/4*32.0*((800.0+6720.0)*2-8*30.0+10*32.0+700.0/100.0*3.14/4*8.0*((200.0+1680.0)*2-8*30.0+10*8.0+ 700.0/100.0 *3.14/4*8.0*((0.0+0.0)*2-8*30.0+10*8.0))))*7.85;
		t = 2.0*(3.14/4)*18.0*(700.0+0*18.0+4000.0+(2*600.0+11200.0)+0*18.0+700.0) *7.85;
		t = ( 2*(3.14/4)*0* ( ( 800.0 + ( 0+12 )*0 )*2.0 + 0*0 + 200.0+ 600.0 + 10200.0 + 0*0.0+800.0+(0+12)*0.0 ) ) *7.85;
		t = ( 10.0*3.14/4*2900.0 * (400.0/200.0)*2
						+ 0*3.14/4*0 * (0/1)*2 )*7.85/1000/1000;
		String expression = "(F(2,1))^3 +F(2,1)";
//		expression = "max(F(2,1),3)^3 +F(2,1)";
		Map<String,Object> params = new HashMap<>();
//		params.put("F(2,1)",2d);
		expression = expression.replace("F(2,1)","2");
//		expression = expression.replace("F(2,1)","2");
		System.out.println("---re--"+evaluate(expression,params));
		System.out.println("---re1--"+getMax(1,2,3,5.12));
		System.out.println("---re1--"+t);

	}
}
